package vip.liux.front.domain.models.chat;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
import vip.liux.domain.entities.AggregateRoot;
import vip.liux.users.IUpdateUserData;
import vip.liux.users.IUser;
import vip.liux.users.IUserData;

import java.util.Objects;

/**
 * 聊天用户
 */
@Getter
@Setter
@Entity
@Table(name = "chat_users")
@org.springframework.data.relational.core.mapping.Table("chat_users")
public class ChatUser extends AggregateRoot<Long, ChatUser> implements IUser<Long>, IUserData<Long>, IUpdateUserData<Long> {

    /**
     * 租户ID
     */
    @Getter
    @Column(name = "tenant_id")
    private String tenantId;

    /**
     * 用户名
     */
    @Size(max = 256)
    @NotNull
    @Column(name = "user_name", nullable = false, length = 256)
    @org.springframework.data.relational.core.mapping.Column("user_name")
    private String username;

    /**
     * 邮箱
     */
    @Size(max = 256)
    @NotNull
    @Column(name = "email", nullable = false, length = 256)
    private String email;

    /**
     * 姓名
     */
    @Size(max = 64)
    @Column(name = "name", length = 64)
    private String name;

    /**
     * 姓氏
     */
    @Size(max = 64)
    @Column(name = "surname", length = 64)
    private String surname;

    /**
     * 是否激活
     */
    @NotNull
    @Column(name = "active", nullable = false)
    private boolean active;

    /**
     * 邮箱是否已验证
     */
    @NotNull
    @Column(name = "email_confirmed", nullable = false)
    private boolean emailConfirmed;

    /**
     * 电话号码
     */
    @Size(max = 16)
    @Column(name = "phone_number", length = 16)
    private String phoneNumber;

    /**
     * 电话号码是否已验证
     */
    @NotNull
    @Column(name = "phone_number_confirmed", nullable = false)
    private boolean phoneNumberConfirmed;

    @Override
    public boolean isActive() {
        return active;
    }

    @Override
    public boolean isEmailVerified() {
        return emailConfirmed;
    }

    @Override
    public boolean isPhoneNumberVerified() {
        return phoneNumberConfirmed;
    }

    protected ChatUser() {
    }

    public ChatUser(IUserData<Long> user) {
        this.setId(user.getId());
        this.tenantId = Objects.requireNonNull(user.getTenantId());
        updateInternal(user);
    }

    /**
     * 更新用户数据
     *
     * @param user 用户数据
     * @return 是否更新成功
     */
    @Override
    public boolean update(@org.jetbrains.annotations.NotNull IUserData<Long> user) {
        if (!Objects.equals(getId(), user.getId())) {
            throw new IllegalArgumentException("Given User's Id " + user.getId() + " does not match to this User's Id " + getId());
        }

        if (!Objects.equals(getTenantId(), user.getTenantId())) {
            throw new IllegalArgumentException("Given User's TenantId " + user.getTenantId() + " does not match to this User's TenantId " + getTenantId());
        }

        if (equals(user)) {
            return false;
        }

        updateInternal(user);

        return true;
    }


    protected boolean equals(IUserData<Long> user) {
        return
                Objects.equals(getId(), user.getId()) &&
                Objects.equals(getTenantId(), user.getTenantId()) &&
                        Objects.equals(getUsername(), user.getUsername()) &&
                        Objects.equals(getName(), user.getName()) &&
                        Objects.equals(getSurname(), user.getSurname()) &&
                        Objects.equals(getEmail(), user.getEmail()) &&
                        Objects.equals(isEmailVerified(), user.isEmailVerified()) &&
                        Objects.equals(getPhoneNumber(), user.getPhoneNumber()) &&
                        Objects.equals(isPhoneNumberVerified(), user.isPhoneNumberVerified());
    }

    /**
     * 更新内部数据
     *
     * @param user 用户数据
     */
    private void updateInternal(IUserData<Long> user) {
        this.email = user.getEmail();
        this.name = user.getName();
        this.surname = user.getSurname();
        this.emailConfirmed = user.isEmailVerified();
        this.phoneNumber = user.getPhoneNumber();
        this.phoneNumberConfirmed = user.isPhoneNumberVerified();
        this.username = user.getUsername();
    }
}